﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using MongoDB.Bson;
using MongoDB.Driver;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Xml.Linq;
using MongoDB.Driver.Builders;

namespace BattleShip_MongoDB
{
    public partial class GameForm : Form
    {
        private const int iFieldSize = 20;  // Size of each square
        private const int iBoardSize = 200; // Size full board
        private const int BoardXSize = iBoardSize / iFieldSize;
        private const int BoardYSize = iBoardSize / iFieldSize;
        private const int ShipsCount = 5;   // Number of ship
        private const int iNoShip5 = 1;
        private const int iNoShip4 = 1;
        private const int iNoShip3 = 2;
        private const int iNoShip2 = 1;
        
        private int[,] m_YourBoard = new int[BoardXSize, BoardYSize];   // Your ship position 1: head ship, 11 body ship, 2: ship down, 3: shot miss
        private int[,] m_EnemyBoard = new int[BoardXSize, BoardYSize];  // Enemy ship position 1: head ship, 11 body ship, 2: ship down, 3: shot miss

        /*Sep 22, 2013: Hoang Nguyen added*/
        private Player Player1 = new Player();
        private Player Player2 = new Player();
        private Ship shipTemp;
        private int iNoShip5Undef;
        private int iNoShip4Undef;
        private int iNoShip3Undef;
        private int iNoShip2Undef;
        private RadioButton rbShipType;
        private RadioButton rbShipDirection;
        private int iShipSize;
        private bool bShipDirection;

        private Image[] m_ShipImage = new Image[5];
        private Image[] m_ShipImageV = new Image[5];
        private Image[] m_Fire = new Image[2];
        private Image[] m_Ocean = new Image[2];
        private Image[] m_Miss = new Image[2];

        private Point m_LastMouseDownPosition;
        private bool m_IsInitialPlacement = true;		
        private Int32 i_currentShip;	// Current type ship 0->4

        public char m_LocalPlayerIndex;	// Player 1 or 2 or 3 is computer
        public bool m_bYourTurn;
        private int CurrStep;
        private bool b_AIMode;
       
        public Position PrevMove = new Position(-1, -1);
        public Position CurrMove = new Position(-1, -1);
        

        private int iReadyPlay = -1;
        private bool bloadstep = false;
        private bool b_Start = false;	// Game start or not
        public bool XPlaying;
        public int iGoal = 0;
        public int iNumberGoal = (iNoShip5 * 5) + (iNoShip4 * 4) + (iNoShip3 * 3) + (iNoShip2 * 2);
        private int iStatus = 0;

        int[] ShipSizeValue = new int[5];
        int[] ShipSizePosition = new int[5];
        bool[] ShipDirectV = new bool[5];
        int AddShipIndex = 0;

        public GameForm()
        {
            InitializeComponent();

            iShipSize = 5;
            i_currentShip = 4;
            bShipDirection = false;
            m_bYourTurn = true;

            UserInformation.mainGame = this;
        }
        #region Game AI code
        // Random ship for AI
        private void AIShot()
        {
            // First just a random shot
            Random random = new Random();
            int rX;
            int rY;
            Point pointAIShot;
            while (true)
            {
                rX = random.Next(BoardXSize);
                rY = random.Next(BoardYSize);

                if ((m_YourBoard[rX, rY] != 3)
                    && (m_YourBoard[rX, rY] != 2))
                {
                    pointAIShot = new Point(rX, rY);

                    Player1.ShotedAt(pointAIShot);

                    if (m_YourBoard[rX, rY] == 1 || m_YourBoard[rX, rY] == 11)
                    {
                        m_YourBoard[rX, rY] = 2;
                        panel1.Invalidate(new Rectangle(rX * iFieldSize + 1, rY * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                        if (Player1.GetNoAliveShip() == 0)
                        {
                            MessageHint.Text = "You lost!";
                            ResetGame();
                        }
                    }
                    else if (m_YourBoard[rX, rY] == 0)
                    {
                        m_YourBoard[rX, rY] = 3;
                        panel1.Invalidate(new Rectangle(rX * iFieldSize + 1, rY * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                        break;
                    }

                }
            } 
        }
        private void GenerateAIShip()
        {
            Random random = new Random();
            Point pointTemp;
            iNoShip2Undef = iNoShip2;
            iNoShip3Undef = iNoShip3;
            iNoShip4Undef = iNoShip4;
            iNoShip5Undef = iNoShip5;

            for (int i = 0; i < ShipsCount; i++)
            {
                int rX=random.Next(BoardXSize);
                int rY=random.Next(BoardYSize);
                int iTemp = random.Next(2);
                bool blDirection;
                int iSizeTemp;

                if (iTemp == 0)
                {
                    blDirection = false;
                }
                else
                {
                    blDirection = true;
                }

                if (iNoShip5Undef != 0)
                {
                    iSizeTemp = 5;
                }
                else if (iNoShip4Undef != 0)
                {
                    iSizeTemp = 4;
                }
                else if (iNoShip3Undef > 0)
                {
                    iSizeTemp = 3;
                }
                else
                {
                    iSizeTemp = 2;
                }


                if (CheckValidToPlaceShip(false, rX, rY, iSizeTemp, blDirection))
                {
                    pointTemp = new Point(rX, rY);

                    shipTemp = new Ship(iSizeTemp, pointTemp, blDirection);

                    Player2.AddShip(shipTemp);

                    for (int j = 0; j < iSizeTemp; j++)
                    {
                        if (blDirection)
                        {
                            m_EnemyBoard[rX, rY + j] = 1;
                        }
                        else
                        {
                            m_EnemyBoard[rX + j, rY] = 1;
                        }
                    }

                    switch (iSizeTemp)
                    {
                        case 2:
                            iNoShip2Undef--;
                            break;
                        case 3:
                            iNoShip3Undef--;
                            break;
                        case 4:
                            iNoShip4Undef--;
                            break;
                        case 5:
                            iNoShip5Undef--;
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    i--;
                }

            }
        }

        #endregion
        #region Game require checking code
        private void ResetGame()
        {
               // Reset board 
            for (int i = 0; i < BoardXSize; i++)
            {
                for (int j = 0; j < BoardYSize; j++)
                {
                    m_YourBoard[i,j]=0;
                    m_EnemyBoard[i, j] = 0;
                }
            }
            m_IsInitialPlacement = true;
            panel2.Visible = false;
            panel1.Invalidate();

            /*Sep 22, 2013: Hoang Nguyen added*/
            iNoShip2Undef = iNoShip2;
            iNoShip3Undef = iNoShip3;
            iNoShip4Undef = iNoShip4;
            iNoShip5Undef = iNoShip5;

            labelShip2CellCount.Text = "Number: " + iNoShip2Undef;
            labelShip3CellCount.Text = "Number: " + iNoShip3Undef;
            labelShip4CellCount.Text = "Number: " + iNoShip4Undef;
            labelShip5CellCount.Text = "Number: " + iNoShip5Undef;

            groupBox1.Visible = true;
            groupBox2.Visible = true;
        }
        private void CheckForCompleteInitialPlacement()
        {
            // Count the number of placed ships
            int PlacementCount = 0;
            for (int i = 0; i < BoardXSize; i++)
            {
                for (int j = 0; j < BoardYSize; j++)
                {
                    if (m_YourBoard[i, j] == 1 || m_YourBoard[i, j] == 11)
                        PlacementCount++;
                }
            }

            // If five ships have been placed, we exit Placement Mode...
            if (PlacementCount == ShipsCount)
            {
                m_IsInitialPlacement = false;

                if (b_Start)
                {
                    panel2.Visible = true;
                    MessageHint.Text = "Game start!";
                }
                if (b_AIMode)                
                GenerateAIShip();
                
              
            }
        }
        public char GetCurrentPlayer()
        {
                if (m_bYourTurn)
                    return '1';
                else
                    return '2';
            
        }        

        public void CheckingStep()
        {
            Position p = null;
            p = loadStep();
        }
        
        #endregion

        #region Game drawing code
        private void PaintSea(Graphics g)
        {
            if (iReadyPlay == -1)
            {
                // Connect to MongoDB
                MongoServer MongoDB = MongoServer.Create();
                MongoDB.Connect();

                var db = MongoDB.GetDatabase("BattleShipDataBase");

                using (MongoDB.RequestStart(db))
                {
                    var collection = db.GetCollection<BsonDocument>("GameRoom");

                    if (UserInformation.gameID != null)
                    {
                        var query = new QueryDocument("GameID", UserInformation.gameID);

                        BsonDocument game = collection.FindOne(query);
                        if (game != null)
                        {
                            if (game["Status"] == "1" && UserInformation.UserName2 != null)
                            {
                                panel2.Visible = true;
                                MessageHint.Text = "Game start!";
                                iReadyPlay = 1;
                                if (UserInformation.isFirst)
                                {
                                    
                                    UserInformation.UserName2 = game["UserName2"].ToString();
                                    label2.Text = "Opponent name: " + UserInformation.UserName2;
                                }
                                else
                                    label2.Text = "Opponent name: " + UserInformation.UserName1;

                                collection = db.GetCollection<BsonDocument>("GameProcess");
                                query = new QueryDocument("GameID", UserInformation.gameID);

                                if (UserInformation.isFirst)
                                {

                                    foreach (BsonDocument item in collection.Find(query))
                                    {
                                        BsonElement Bsonstep = item.GetElement("step");
                                        BsonElement Bsonx = item.GetElement("x");
                                        BsonElement Bsony = item.GetElement("y");
                                        BsonElement Bsonvalue = item.GetElement("value");
                                        int iStep = Convert.ToInt32(Bsonstep.Value);
                                        int xx = Convert.ToInt32(Bsonx.Value);
                                        int yy = Convert.ToInt32(Bsony.Value);
                                        int value = Convert.ToInt32(Bsonvalue.Value);
                                        if (iStep == -2)
                                        {
                                            m_EnemyBoard[xx, yy] = value;
                                        }
                                    }
                                    UserInformation.step = 0;
                                }
                                else
                                {
                                    foreach (BsonDocument item in collection.Find(query))
                                    {
                                        BsonElement Bsonstep = item.GetElement("step");
                                        BsonElement Bsonx = item.GetElement("x");
                                        BsonElement Bsony = item.GetElement("y");
                                        BsonElement Bsonvalue = item.GetElement("value");
                                        int iStep = Convert.ToInt32(Bsonstep.Value);
                                        int xx = Convert.ToInt32(Bsonx.Value);
                                        int yy = Convert.ToInt32(Bsony.Value);
                                        int value = Convert.ToInt32(Bsonvalue.Value);
                                        if (iStep == -1)
                                        {
                                            m_EnemyBoard[xx, yy] = value;
                                        }
                                    }
                                    UserInformation.step = 0;
                                }
                                
                            }
                        }
                    }
                }
            }

            //g.Clear(Color.SlateBlue);
            g.DrawImage(m_Ocean[1], new Rectangle(0, 0, iBoardSize, iBoardSize));
            for (int i = 0; i <= BoardXSize; i++)
            {
                for (int j = 0; j <= BoardYSize; j++)
                {
                    g.DrawLine(System.Drawing.Pens.DarkBlue, i * iFieldSize, 0, i * iFieldSize, iBoardSize);
                    g.DrawLine(System.Drawing.Pens.DarkBlue, 0, j * iFieldSize, iBoardSize, j * iFieldSize);
                }
            }
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            if (iStatus == -1)
            {
                if (UserInformation.isFirst)
                    MessageHint.Text = "You Win!";
                else
                    MessageHint.Text = "You Lose!";
            }
            else if (iStatus == -2)
            {
                if (UserInformation.isFirst)
                    MessageHint.Text = "You Lose!";
                else
                    MessageHint.Text = "You Win!";
            }

            if ((XPlaying == false && bloadstep == false && iReadyPlay == 1))
            {
                Thread th = new Thread(CheckingStep);
                th.Start();
            }
            PaintSea(e.Graphics);            
           
            for (int i = 0; i < BoardXSize; i++)
            {
                for (int j = 0; j < BoardYSize; j++)
                {
                    if (m_YourBoard[i, j] == 2) 
                    {
                        e.Graphics.DrawImage(m_Fire[1], new Rectangle(i * iFieldSize + 1, j * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                    }
                    else if (m_YourBoard[i, j] == 3)
                    {
                        //e.Graphics.FillEllipse(Brushes.Red, i * iFieldSize + 5, j * iFieldSize + 5, 10, 10);
                        e.Graphics.DrawImage(m_Miss[1], new Rectangle(i * iFieldSize + 1, j * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                    }
                }
            }

            for (int i = 0; i < AddShipIndex; i++)
            {
                int x = ShipSizePosition[i] % BoardXSize;
                int y = ShipSizePosition[i] / BoardYSize;
                if (ShipDirectV[i])
                    e.Graphics.DrawImage(m_ShipImageV[ShipSizeValue[i]], new Rectangle(x * iFieldSize, y * iFieldSize, iFieldSize, iFieldSize * (ShipSizeValue[i] + 1)));
                else
                    e.Graphics.DrawImage(m_ShipImage[ShipSizeValue[i]], new Rectangle(x * iFieldSize, y * iFieldSize, iFieldSize * (ShipSizeValue[i] + 1), iFieldSize));
            }
        }      
        
        private void panel2_Paint(object sender, PaintEventArgs e)
        {
            PaintSea(e.Graphics);

            for (int i = 0; i < BoardXSize; i++)
            {
                for (int j = 0; j < BoardYSize; j++)
                {
                    if (m_EnemyBoard[i, j] == 1)
                    {
                        // Draw enemy ship
                        //e.Graphics.FillRectangle(Brushes.White, i * iFieldSize + 1, j * iFieldSize + 1, iFieldSize - 1, iFieldSize-1);
                       //e.Graphics.DrawImage(m_ShipImage[i_currentShip], i * iFieldSize + 4, j * iFieldSize + 4);
                    }
                    if (m_EnemyBoard[i, j] == 2)
                    {
                        //e.Graphics.FillRectangle(Brushes.Red, i * iFieldSize + 1, j * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1);
                        e.Graphics.DrawImage(m_Fire[1], new Rectangle(i * iFieldSize + 1, j * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                    }
                    else if (m_EnemyBoard[i, j] == 3)
                    {
                        // e.Graphics.FillEllipse(Brushes.Red, i * iFieldSize + 5, j * iFieldSize + 5, 10, 10);
                        e.Graphics.DrawImage(m_Miss[1], new Rectangle(i * iFieldSize + 1, j * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                    }
                }
            }
        }
        #endregion

        #region Game event code
        private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            int DownGridX = (int)(m_LastMouseDownPosition.X / iFieldSize);
            int DownGridY = (int)(m_LastMouseDownPosition.Y / iFieldSize);
            int UpGridX = (int)(e.X / iFieldSize);
            int UpGridY = (int)(e.Y / iFieldSize);
            bool blIsValidToProcess = false;
            Point pointTemp;

            if (DownGridX == UpGridX && DownGridY == UpGridY)
            {
                // We have a grid click
                if (m_IsInitialPlacement)
                {
                    // TODO: Add this click to the Initial Placement of ships

                    switch (iShipSize)
                    {
                        case 2:
                            if (iNoShip2Undef != 0)
                            {
                                blIsValidToProcess = true;
                            }
                            break;
                        case 3:
                            if (iNoShip3Undef != 0)
                            {
                                blIsValidToProcess = true;
                            }
                            break;
                        case 4:
                            if (iNoShip4Undef != 0)
                            {
                                blIsValidToProcess = true;
                            }
                            break;
                        case 5:
                            if (iNoShip5Undef != 0)
                            {
                                blIsValidToProcess = true;
                            }
                            break;
                        default:
                            break;
                    }

                    if (blIsValidToProcess)
                    {
                        if (CheckValidToPlaceShip(true, UpGridX, UpGridY, iShipSize, bShipDirection))
                        {
                            pointTemp = new Point(UpGridX, UpGridY);

                            shipTemp = new Ship(iShipSize, pointTemp, bShipDirection);

                            Player1.AddShip(shipTemp);

                            PlaceShipOnBoard(shipTemp);
                            ShipSizeValue[AddShipIndex] = i_currentShip;
                            ShipSizePosition[AddShipIndex] = UpGridX + UpGridY * BoardYSize;
                            ShipDirectV[AddShipIndex] = bShipDirection;
                            AddShipIndex++;

                            if (Player1.GetNoValidShip() == ShipsCount)
                            {
                                m_IsInitialPlacement = false;
                                groupBox1.Visible = false;
                                groupBox2.Visible = false;

                                //Save Ship User
                                if (UserInformation.isFirst)
                                {
                                    for (int i = 0; i < BoardXSize; i++)
                                    {
                                        for (int j = 0; j < BoardYSize; j++)
                                        {
                                            if (m_YourBoard[i, j] == 1 || m_YourBoard[i, j] == 11)
                                            {
                                                UserInformation.step = -1;
                                                saveStep(i, j, m_YourBoard[i, j], 1, true);
                                            }
                                        }
                                    }
                                   
                                }
                                else
                                {
                                    for (int i = 0; i < BoardXSize; i++)
                                    {
                                        for (int j = 0; j < BoardYSize; j++)
                                        {
                                            if (m_YourBoard[i, j] == 1 || m_YourBoard[i, j] == 11)
                                            {
                                                UserInformation.step = -2;
                                                saveStep(i, j, m_YourBoard[i, j], 1, true);
                                            }
                                        }
                                    }

                                    b_Start = true;

                                    // Connect to MongoDB
                                    MongoServer MongoDB = MongoServer.Create();
                                    MongoDB.Connect();

                                    var db = MongoDB.GetDatabase("BattleShipDataBase");

                                    using (MongoDB.RequestStart(db))
                                    {
                                        var collection = db.GetCollection<BsonDocument>("GameRoom");

                                        if (UserInformation.gameID != null)
                                        {
                                            var query = new QueryDocument("GameID", UserInformation.gameID);

                                            BsonDocument game = collection.FindOne(query);
                                            if (game != null)
                                            {
                                                game["Status"] = "1";
                                                collection.Save(game);
                                            }
                                        }
                                    }
                                    MongoDB.Disconnect();
                                }

                                if (b_Start)
                                {
                                    panel2.Visible = true;
                                    MessageHint.Text = "Game start!";
                                }

                                if (b_AIMode)
                                {
                                    GenerateAIShip();
                                }
                            }
                            else
                            {
                                switch (iShipSize)
                                {
                                    case 2:
                                        iNoShip2Undef--;
                                        labelShip2CellCount.Text = "Number: " + iNoShip2Undef;
                                        break;
                                    case 3:
                                        iNoShip3Undef--;
                                        labelShip3CellCount.Text = "Number: " + iNoShip3Undef;
                                        break;
                                    case 4:
                                        iNoShip4Undef--;
                                        labelShip4CellCount.Text = "Number: " + iNoShip4Undef;
                                        break;
                                    case 5:
                                        iNoShip5Undef--;
                                        labelShip5CellCount.Text = "Number: " + iNoShip5Undef;
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }
                        else
                        {
                            MessageBox.Show("Out of range, please choose another position or direction!", "Infor", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    else
                    {
                        MessageBox.Show("Not enough ship type to place, please choose another ship type!", "Infor", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }


                }
            }
        }

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            m_LastMouseDownPosition = new Point(e.X, e.Y);
        }

     

        private void GameForm_Load(object sender, EventArgs e)
        { 
            // Disable board 2 when start
            panel2.Visible = false;

            // Load image ship         
            m_ShipImage[1] = (Image)Properties.Resources.ResourceManager.GetObject("patrol");
            m_ShipImage[2] = (Image)Properties.Resources.ResourceManager.GetObject("submarine");
            m_ShipImage[3] = (Image)Properties.Resources.ResourceManager.GetObject("seawolf");
            m_ShipImage[4] = (Image)Properties.Resources.ResourceManager.GetObject("carrier");
            // image ship vertical
            m_ShipImageV[1] = (Image)Properties.Resources.ResourceManager.GetObject("patrol_v");
            m_ShipImageV[2] = (Image)Properties.Resources.ResourceManager.GetObject("submarine_v");
            m_ShipImageV[3] = (Image)Properties.Resources.ResourceManager.GetObject("seawolf_v");
            m_ShipImageV[4] = (Image)Properties.Resources.ResourceManager.GetObject("carrier_v");
            // image fire
            m_Fire[1] = (Image)Properties.Resources.ResourceManager.GetObject("fire");
            // image ocean
            m_Ocean[0] = (Image)Properties.Resources.ResourceManager.GetObject("ocean1");
            m_Ocean[1] = (Image)Properties.Resources.ResourceManager.GetObject("ocean2");

            //image miss 
            m_Miss[1] = (Image)Properties.Resources.ResourceManager.GetObject("miss");

            char playerSymbol = '1';
            if (UserInformation.isFirst) playerSymbol = '1';
            else playerSymbol = '2';
            NewGame(UserInformation.isFirst, playerSymbol);
            if (UserInformation.isFirst)
            {
                label1.Text = "Your name: " + UserInformation.UserName1;

            }
            else
                label1.Text = "Your name: " + UserInformation.UserName2;
            label2.Text = "";
        }

        private void GameForm_Closed(object sender, FormClosedEventArgs e)
        {
            UserInformation.LogOut();
            Application.Exit();
        }

        private void GameForm_Closing(object sender, FormClosingEventArgs e)
        {
            if (iStatus == -1 || iStatus == -2)
             {
                const string message = "Bạn có muốn trở lại Game Room?";
                const string caption = "Hello";
                var result = MessageBox.Show(message, caption,
                                             MessageBoxButtons.YesNo,
                                             MessageBoxIcon.Question);

                // If the no button was pressed ... 
                if (result == DialogResult.No)
                {
                    UserInformation.LogOut();
                    Application.Exit();
                    // cancel the closure of the form.
                    //e.Cancel = true;
                }
                else
                {
                    e.Cancel = true;
                    UserInformation.mainGame.Hide();
                    if (UserInformation.gameRoom == null)
                        UserInformation.gameRoom = new GameRoom();
                    UserInformation.gameRoom.Show();
                    UserInformation.gameRoom.UpdateGameRoom();
                }
                iStatus = 0;
            }
            else
            {
                const string message = "Bạn thật sự muốn thoát?";
                const string caption = "Thoát Game";
                var result = MessageBox.Show(message, caption,
                                             MessageBoxButtons.YesNo,
                                             MessageBoxIcon.Question);

                // If the no button was pressed ... 
                if (result == DialogResult.No)
                {
                    // cancel the closure of the form.
                    e.Cancel = true;
                }
                else
                {
                    UserInformation.LogOut();
                }
            }
        }

        
        private void panel2_MouseDown(object sender, MouseEventArgs e)
        {
            m_LastMouseDownPosition = new Point(e.X, e.Y);
        }

        private void panel2_MouseUp(object sender, MouseEventArgs e)
        {
            if (iStatus == -1 || iStatus == -2)
                return;
            if (XPlaying == false)
            { 
                String strMessage = "";
                if (UserInformation.isFirst)
                    strMessage = "Please waiting for user: " + UserInformation.UserName2;
                else
                    strMessage = "Please waiting for user: " + UserInformation.UserName1;

                var result = MessageBox.Show(strMessage, "Hello!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;

            }
            int DownGridX = (int)(m_LastMouseDownPosition.X / iFieldSize);
            int DownGridY = (int)(m_LastMouseDownPosition.Y / iFieldSize);
            int UpGridX = (int)(e.X / iFieldSize);
            int UpGridY = (int)(e.Y / iFieldSize);

            if (UpGridX >= BoardXSize || UpGridY >= BoardYSize)
                return;
            Point shotPoint;

            if (DownGridX == UpGridX && DownGridY == UpGridY)
            {
                // We have a grid click

                shotPoint = new Point(UpGridX, UpGridY);
                CurrMove.Set(UpGridX, UpGridY);
                Player1.ShotedAt(shotPoint);

                if (m_EnemyBoard[UpGridX, UpGridY] == 1 || m_EnemyBoard[UpGridX, UpGridY] == 11)
                {
                    bloadstep = false;
                    XPlaying = false;
                    m_EnemyBoard[UpGridX, UpGridY] = 2;

                    if (UserInformation.isFirst)
                        saveStep(UpGridX, UpGridY, m_EnemyBoard[UpGridX, UpGridY], 2);
                    else
                        saveStep(UpGridX, UpGridY, m_EnemyBoard[UpGridX, UpGridY], 1);
                    iGoal++;
                    if (iGoal == iNumberGoal)
                    {
                        MessageHint.Text = "You win!";
                        if (UserInformation.isFirst)
                        {
                            saveUserResult(UserInformation.UserName1, true);
                            saveUserResult(UserInformation.UserName2, false);
                            saveGameResult("-1");
                            iStatus = -1;
                        }
                        else
                        {
                            saveUserResult(UserInformation.UserName2, true);
                            saveUserResult(UserInformation.UserName1, false);
                            saveGameResult("-2");
                            iStatus = -2;
                        }
                        //ResetGame();
                    }
                }
                else if (m_EnemyBoard[UpGridX, UpGridY] == 0)
                {
                    bloadstep = false;
                    XPlaying = false;
                    m_EnemyBoard[UpGridX, UpGridY] = 3;
                    if (b_AIMode)
                        AIShot();

                    if (UserInformation.isFirst)
                        saveStep(UpGridX, UpGridY, m_EnemyBoard[UpGridX, UpGridY], 2);
                    else
                        saveStep(UpGridX, UpGridY, m_EnemyBoard[UpGridX, UpGridY], 1);
                }

                panel2.Invalidate(new Rectangle(UpGridX * iFieldSize + 1, UpGridY * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                    
            }
        }
             
        private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            XPlaying = true;
            b_AIMode = true; // Practice with bot
            b_Start = true;
            ResetGame();
            MessageHint.Text = "Place your ships";
        }

        public void NewGame(bool playerFirst, char playerSymbol)
        {            
            ResetGame();
            Invalidate();
            if (playerFirst)
            {
                XPlaying = playerSymbol == '1' ? true : false;
                CurrMove.Set(-1, -1);
            }
            else
            {
                XPlaying = playerSymbol == '1' ? true : false;
            }
        }
        private void GameForm_Activated(object sender, EventArgs e)
        {
            panel1.Refresh();
            panel2.Refresh();
        }

        #endregion

        #region Init event Code
        private void GroupShipTypeAllCheckBoxes_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
            {
                rbShipType = (RadioButton)sender;
            }

            if (rbShipType == radioButtonShip2Cell)
            {
                iShipSize = 2;
                i_currentShip = 1;
            }
            else if (rbShipType == radioButtonShip3Cell)
            {
                iShipSize = 3;
                i_currentShip = 2;
            }
            else if (rbShipType == radioButtonShip4Cell)
            {
                iShipSize = 4;
                i_currentShip = 3;
            }
            else
            {
                iShipSize = 5;
                i_currentShip = 4;
            }

            return;
        }

        private void GroupShipDirectionAllCheckBoxes_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
            {
                rbShipDirection = (RadioButton)sender;
            }

            if (rbShipDirection == radioButtonHorizon)
            {
                bShipDirection = false;
            }
            else
            {
                bShipDirection = true;
            }

            return;
        }
        #endregion

        #region Game init Code
        private bool CheckValidToPlaceShip(bool blIsPlayer1, int x, int y, int iSize, bool blDirection)
        {
            bool blRetStatus = false;
            int i;

            if (blDirection)
            {
                if (y + iSize <= BoardYSize)
                {
                    for (i = 0; i < iSize; i++)
                    {
                        if (blIsPlayer1)
                        {
                            if (m_YourBoard[x, y + i] != 0)
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (m_EnemyBoard[x, y + i] != 0)
                            {
                                break;
                            }
                        }
                    }

                    if (i == iSize)
                    {
                        blRetStatus = true;
                    }
                }
            }
            else
            {
                if (x + iSize <= BoardXSize)
                {
                    for (i = 0; i < iSize; i++)
                    {
                        if (blIsPlayer1)
                        {
                            if (m_YourBoard[x + i, y] != 0)
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (m_EnemyBoard[x + i, y] != 0)
                            {
                                break;
                            }
                        }
                    }

                    if (i == iSize)
                    {
                        blRetStatus = true;
                    }
                }
            }

            return blRetStatus;
        }

        private void PlaceShipOnBoard(Ship ship)
        {
            int iSizeTemp = ship.GetShipSize();
            bool blDirectionTemp = ship.GetShipDirection();
            Point pointTemp = ship.GetShipTopLeftPosition();
            if (blDirectionTemp)
                panel1.Invalidate(new Rectangle(pointTemp.X * iFieldSize + 1, pointTemp.Y * iFieldSize + 1, iFieldSize - 1, iFieldSize * (i_currentShip + 1)));    
            else                
                panel1.Invalidate(new Rectangle(pointTemp.X * iFieldSize + 1, pointTemp.Y * iFieldSize + 1, iFieldSize * (i_currentShip + 1), iFieldSize - 1));    
            
            m_YourBoard[pointTemp.X, pointTemp.Y] = 1;
            for (int i = 1; i < iSizeTemp; i++)
            {
                if (blDirectionTemp)
                {
                    m_YourBoard[pointTemp.X, pointTemp.Y + i] = 11;
                    //panel1.Invalidate(new Rectangle(pointTemp.X * iFieldSize + 1, (pointTemp.Y + i) * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                }
                else
                {
                    m_YourBoard[pointTemp.X + i, pointTemp.Y] = 11;
                    //panel1.Invalidate(new Rectangle((pointTemp.X + i) * iFieldSize + 1, pointTemp.Y * iFieldSize + 1, iFieldSize - 1, iFieldSize - 1));
                }
            }
        }
        #endregion

        #region Game database
        private void saveStep(int x, int y, int value, int MTindex, bool isAddingShip = false)
        {
            // Connect to MongoDB
            MongoServer mongo = MongoServer.Create();
            mongo.Connect();

            var db = mongo.GetDatabase("BattleShipDataBase");

            using (mongo.RequestStart(db))
            {
                var collection = db.GetCollection<BsonDocument>("GameProcess");

                BsonDocument new_user = new BsonDocument()
                    .Add("GameID", UserInformation.gameID)
                    .Add("UserName", UserInformation.UserName)
                    .Add("step", UserInformation.step)
                    .Add("x", x)
                    .Add("y", y)
                    .Add("value", value)
                    .Add("MTID", MTindex);


                collection.Insert(new_user);
                if (isAddingShip == false)
                    UserInformation.step++;
            }

            mongo.Disconnect();
        }

        private Position loadStep()
        {
            Position p = null;
            //System.Threading.Thread.Sleep(500);
            while (p == null)
            {
                // Connect to MongoDB
                MongoServer mongo = MongoServer.Create();
                mongo.Connect();

                var db = mongo.GetDatabase("BattleShipDataBase");

                using (mongo.RequestStart(db))
                {
                    var collection = db.GetCollection<BsonDocument>("GameProcess");
                    var query = Query.And(
                                 Query.EQ("GameID", UserInformation.gameID),
                                 Query.EQ("step", UserInformation.step)
                                 //Query.NE("UserName", UserInformation.UserName)
                                 );

                    BsonDocument stepGame = collection.FindOne(query);
                    if (stepGame != null && XPlaying == false)
                    {
                        XPlaying = true;
                        bloadstep = true;
                        
                        String x = stepGame["x"].ToString();
                        String y = stepGame["y"].ToString();
                        String MTID = stepGame["MTID"].ToString();
                        String value = stepGame["value"].ToString();
                        p = new Position(x, y);

                        UserInformation.MTIndex = Convert.ToInt32(MTID);                        
                        int xx = Convert.ToInt32(x);
                        int yy = Convert.ToInt32(y);
                        int ivalue = Convert.ToInt32(value);
                        UserInformation.step++;

                        if (UserInformation.isFirst)
                        {
                            if (UserInformation.MTIndex == 1)
                                m_YourBoard[xx, yy] = ivalue;
                            else if (UserInformation.MTIndex == 2)
                                m_EnemyBoard[xx, yy] = ivalue;
                        }
                        else
                        {
                            if (UserInformation.MTIndex == 1)
                                m_EnemyBoard[xx, yy] = ivalue;
                            else if (UserInformation.MTIndex == 2)
                                m_YourBoard[xx, yy] = ivalue;
                        }                        

                        if (UserInformation.UserName2.Equals(""))
                            UserInformation.UserName2 = stepGame["UserName"].ToString();

                        collection = db.GetCollection<BsonDocument>("GameRoom");
                        query = new QueryDocument("GameID", UserInformation.gameID);

                        BsonDocument gameItem = collection.FindOne(query);
                        if (gameItem != null)
                        {
                            String status = gameItem["Status"].ToString();
                            if (status == "-2" || status == "-1")
                            {                                
                                iStatus = Convert.ToInt32(status);
                            }
                        }
                    }
                }

                mongo.Disconnect();

                System.Threading.Thread.Sleep(1000);
            }
            return p;
        }

        private void saveUserResult(String Username, bool iwin)
        {
            MongoServer MongoDB = MongoServer.Create();
            MongoDB.Connect();

            var db = MongoDB.GetDatabase("BattleShipDataBase");

            using (MongoDB.RequestStart(db))
            {
                var collection = db.GetCollection<BsonDocument>("Users");

                if (Username != null)
                {
                    var query = new QueryDocument("UserName", Username);

                    BsonDocument UserInfo = collection.FindOne(query);
                    if (UserInfo != null)
                    {
                        if (iwin)
                        {
                            String NBWin = UserInfo["NumberOfWin"].ToString();
                            int iNBWin = Convert.ToInt32(NBWin);
                            iNBWin++;
                            UserInfo["NumberOfWin"] = Convert.ToString(iNBWin);
                            collection.Save(UserInfo);
                        }
                        else
                        {
                            String NBLost = UserInfo["NumberOfLost"].ToString();
                            int iNBLost = Convert.ToInt32(NBLost);
                            iNBLost++;
                            UserInfo["NumberOfLost"] = Convert.ToString(iNBLost);
                            collection.Save(UserInfo);
                        }
                    }
                }
            }
            MongoDB.Disconnect();
        }

        private void saveGameResult(String status)
        {
            MongoServer MongoDB = MongoServer.Create();
            MongoDB.Connect();

            var db = MongoDB.GetDatabase("BattleShipDataBase");

            using (MongoDB.RequestStart(db))
            {
                var collection = db.GetCollection<BsonDocument>("GameRoom");

                if (UserInformation.gameID != null)
                {
                    var query = new QueryDocument("GameID", UserInformation.gameID);

                    BsonDocument GameInfo = collection.FindOne(query);
                    if (GameInfo != null)
                    {
                        GameInfo["Status"] = status;
                        collection.Save(GameInfo);
                    }
                }
            }
            MongoDB.Disconnect();
        }
        #endregion

        


    } 
}
